/**
 * json 转 html  json.JsonOutputFormat   
 * jsonstring 转html  json.get
 * str 转 json json.parse
 * @param {type} out
 * @return {undefined}
 */
(function(out,options){
      String.prototype.escapeHtml=function(){
            var s = "";
            s = this.replace(/&/g, "&amp;");
            s = s.replace(/</g, "&lt;");
            s = s.replace(/>/g, "&gt;");
            s = s.replace(/ /g, "&nbsp;");
            s = s.replace(/\'/g, "&#39;");
            s = s.replace(/\"/g, "&quot;");
            s = s.replace(/\n/g, "<br>");
            return s;
        }
    out.JsonOutputFormat =function(json){
        return format(json, 0);
    }
    out.get=function(text){
        var json=parse(text);
        return json && json.toString() ?  format(json, 0) : '';    
    }
    out.parse=parse;
    out.addCloseButton=addCloseButton;
    
    function parse(text,notry){
        var jobj;
        try{
            jobj=JSON.parse(text);    
        }catch(e) {}
        
        if(!notry && !jobj && text.match(/\{/)) {
                jobj=[];
                var jarray=find(text);
                console.log(jarray);
                if(jarray)   {
                    jarray.forEach(function(t){
                        var json=parse(t,1);
                        if(json)     jobj.push(json);
                    })
                }
          }
          
         return jobj
    }
    
    function find(text){
        var i=text.indexOf('{');
        var rt=[],tags={'"':'"',"'":"'","{":"}","[":"]"};
        while(i>-1 && i < text.length){

                var n=0,j=i,stack=['{'],tag;
                while(++j) {
                    var tagBegin=stack[stack.length-1];
                    var tagEnd=tags[tagBegin];
                    
                    if(text[j] == tagEnd && text[j-1]!="\\")  {
                        stack.pop();
                    }else if(tags[text[j]]  && text[j-1]!="\\")  {
                        stack.push(text[j])
                    }
                    
                    if(stack.length==0 || (tagEnd!="{" &&  text[j] == "\n") || j>=text.length) { 
                        n=j-i;
                        break;
                    }
                }
                var jsonText=text.substr(i,n+1);
                var f=0;
                
                while(tag=stack.pop()) {
                    f++;
                    if(tag=="[") tag=',"..."]';
                    else if(tag=="{")  {
                        var re={'{':' ',    ',':',"more":"..."}',     ':':":null}"}
                        var ii=jsonText.length;
                        while(ii-- && !re[jsonText[ii]]) ;
                        
                        if(f==1 && re[jsonText[ii]]){
                            jsonText=jsonText.substr(0,ii)+re[jsonText[ii]];
                            continue;
                        }
                        tag=',"more":"..."}';                         
                    }else{
                        var re={'{':' ',    ',':' ',     ':':" "}
                        var ii=jsonText.length;
                        while(ii-- && !re[jsonText[ii]]) ;
                        if(jsonText[ii]=="," && stack[0]=="{") tag+=":null";
                    }
                    
                    //双引号转义 
                    if(tag.length>1) {
                        var nc=function (a,c){
                            var i,n=0;
                            for(i=a.length;i;i--) 
                                if(a[i-1] ==c) 
                                    n++;
                            return n;
                        };
                        var nn=nc(stack,'"');
                        while(nn--) tag=tag.replace(/"/g,'\\"')
                    }
                    
                     jsonText+=tag;
                }
                rt.push(jsonText)
                i=text.indexOf('{',i+n);
        }
        
        return rt;
    }
    function format(){
        var json=arguments[0]?arguments[0]:{};
        var level=arguments[1]?arguments[1]:0;
        var output='';
        var indent=getIndent(level);
        if(isArray(json)){
            output=wrap('brace-array','[');
            output+='<span class="collapsible">';
            output+=loop(json, level+1);
            output+='</span>';
            output+=wrap('brace-array',indent+']');
        }
        else if(typeof(json) == 'object'){
            output=wrap('brace-object','{');
            output+='<span class="collapsible">';
            output+=loop(json, level+1);
            output+='</span>';
            output+=wrap('brace-object',indent+'}');
        }
        
        return output;
    }
    function loop(json, level){
        var output='';
        var header=true;
        var indent=getIndent(level);
        var isArr=isArray(json);
        for(var k in json){
            if(!header){
                output+=wrap('comma', ',');
                output+='<br>';
            }
            else{
                header=false;
            }
            if(!isArr){
                 let name =(options && options.enableKeyWarp)? '<em>"</em>'+k+'<em>"</em>' : k;
                output+=indent+wrap('key-name', name);
                output+=': ';
            }
            else{
                output+=indent;
            }
            
            if(typeof(json[k]) == 'string'){
                var css='value-number';
                if(json[k][0]=='{' || json[k][0]=='[') css+=" json-string level-"+level;
                output+=wrap(css, '"'+json[k].escapeHtml()+'"');
            }
            else if(typeof(json[k]) == 'number'){
                output+=wrap('value-string', json[k]);
            }
            else if(typeof(json[k]) == 'boolean'){
                output+=wrap('value-string',json[k] ? 'true': 'false');
            }else if(json[k] == null){
                output+=wrap('value-string','null');
            }else{
                output+=format(json[k], level)
            }
        }
        return output;
    }
    function isArray(object){
        return  object && typeof object==='object' &&    
                typeof object.length==='number' &&  
                typeof object.splice==='function' &&    
                 //判断length属性是否是可枚举的 对于数组 将得到false  
                !(object.propertyIsEnumerable('length'));
    }
    function getIndent(level){
        var indent='';
        for(var i=0;i<level;i++){
            indent+='&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
        }
        return indent;
    }
    function wrap(c, content){
        return '<span class="'+c+'">'+content+'</span>';
    }
    
    function addCloseButton(root){
        var list=root.getElementsByClassName('collapsible'),i=0,e,a,b;
        for(;i<list.length;i++){
            e=list[i]
            a=document.createElement('i');
            a.innerHTML='';
            a.setAttribute("class","flexible");
            a.box=e;
            a.onclick=function(){
                let box_start=this.nextElementSibling.className.match(/^brace-/) ? this.nextElementSibling: this.nextElementSibling.nextElementSibling;
                let box_end=this.box.nextElementSibling;  
                if(!this.className.match(/closed/)){
                    let count=this.box.innerText.split("\n").length;
                    this.box.style.display="none"
                    this.box.isClosed=true;
                    this.className+=" closed";
                    box_start.className+=" closed";
                    box_start.setAttribute("data-content-after","  ..."+count+"行  ")
                    box_end.value=box_end.innerHTML;
                    box_end.innerHTML=box_end.innerHTML[box_end.innerHTML.length-1];
                }else{
                    this.box.style.display="block"
                    this.box.isClosed=false;
                    this.className=this.className.replace(/ closed/,'')
                    box_start.className=box_start.className.replace(/ closed/,'');
                    box_end.innerHTML=box_end.value;
                }
            };
            b=e.previousElementSibling.previousSibling
            
            b && b.data && b.data.match(/:/) 
            ? e.parentElement.insertBefore(a,e.previousElementSibling.previousElementSibling)
            : e.parentElement.insertBefore(a,e.previousElementSibling);
            if(b && b.data=='"') {
                e.parentElement.parentElement.insertBefore(a,e.parentElement.previousElementSibling);
            }
            
            e.key=a.nextElementSibling;
            e.key.box=e;
        }
    }
    
            
    //页面单击 尝试寻找 .json-string 元素进行解析  
    document.addEventListener('click',function(event){
        var c=event.target.getAttribute('class'),g;
        if(c){
            g=c.match(/json-string level-(\d+)/);
            if(c.match(/value-number/) && event.target.innerText.match(/^"http:../)){
                event.target.innerHTML=`<a href=${event.target.innerText} target=_blank> ${event.target.innerText.escapeHtml()}</a>`;
            }
        }
        
        if(g){
                var t=event.target.innerText;
                var jobj=parse(t.substr(1,t.length-2));
                if(jobj && jobj.toString()) {
                    var html=format(jobj,parseInt(g[1]));
                    event.target.innerHTML='"'+html+'"';
                     event.target.setAttribute('class','value-number')
                     addCloseButton(event.target);
//                    var e=event.target,p=document.createElement('p');
//                    p.innerHTML='"'+html+'"';
//                    e.parentElement.insertBefore(p,e.nextSibling);
                }
        }
    })
})(window.json={},bridge.options);